<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>[1.29]-开放与封闭：多入口和统一初始化 | PhalApi(π框架) - PHP轻量级开源接口框架 - 助你创造价值！</title>
    <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
    <meta content="yes" name="apple-mobile-web-app-capable">
    <meta content="black" name="apple-mobile-web-app-status-bar-style">
    <meta content="telephone=no" name="format-detection">
    <meta content="email=no" name="format-detection">
    <meta name="Author" content="PhalApi,ecitlm,dogstar">
    <meta name="description" content="[1.29]-开放与封闭：多入口和统一初始化，PhalApi是一个PHP轻量级开源接口框架，致力于快速开发接口服务。支持HTTP/SOAP/RPC等协议，可用于搭建接口/微服务/RESTful接口/Web Services。我们不断更新，保持生气；为接口负责，为开源负责！并承诺永久免费！">
    <meta name="keywords" content="PhalApi,phalapi,phalapi接口开发,后台接口开发,后台接口开发框架,接口开发,接口框架,开源接口框架,PHP后台接口开发,PHP接口开发,PHP接口框架,PHP后台接口框架,phalapi官网,PHP接口框架,php接口开发框架,php接口开发,php web框架,π框架,π开发框架,π接口框架,π接口开发框架,api接口,php接口,,PHP接口框架,phalapi文档,phalapi wiki,PhalApi文档,phalapi在线文档,phalapi官方文档">

    <link rel="stylesheet" type="text/css" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" media="screen">
    <link rel="stylesheet" type="text/css" href="https://cdn.bootcss.com/font-awesome/4.7.0/css/font-awesome.css" media="screen">
    <link rel="stylesheet" href="../css/main.css" />
    <link rel="stylesheet" href="../css/loading_bar.css" />
    <link rel="icon" href="http://webtools.qiniudn.com/dog_catch.png" type="image/x-icon" />
    <script src="../js/pace.min.js"></script>
	
	<!-- 代码高亮 -->
	<link rel="stylesheet" href="../css/highlight.min.css">
	<script src="../js/highlight.min.js"></script>
	<script>hljs.initHighlightingOnLoad();</script>
    
</head>

<body>
    <!-- navbar start -->
    <div class="navbar navbar-default navbar-fixed-top" id="mainnav" role="navigation">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="sr-only">Toggle navigation</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <a class="navbar-brand website_name" href="/"><!-- <span>PhalApi</span> --><strong>PhalApi</strong></a>
            </div>
            <div class="navbar-collapse collapse" aria-expanded="false" style="height: 1px;">
                <ul class="nav navbar-nav navbar-right" id="nav_bar">
                    <li><a href="/"><span class="glyphicon glyphicon-home"></span></a></li>
                    <li><a href="http://qa.phalapi.net/">社区</a></li>
                    <li><a href="/download.html">下载</a></li>
                    <li class="active"><a href="/wikis/">文档</a></li>
                    <li><a href="http://www.ituring.com.cn/book/2405">书籍</a></li>
                    <li><a href="http://demo.phalapi.net/">体验</a></li>
                    <li><a href="/about.html">关于</a></li>
                    <li><a href="/donate.html">贡献</a></li>
                    <li><a href="/wikis/en/">English</a></li>
                </ul>
            </div>
            <!--/.nav-collapse -->
        </div>
    </div>
    <!-- navbar end -->


    <div id="content">
        <div class="container">
            <div class="row row-md-flex row-md-flex-wrap">
                <h4><a href="/wikis/%5B1.28%5D-COOKIE%EF%BC%9A%E5%AF%B9COOKIE%E5%8E%9F%E7%94%9F%E6%80%81%E7%9A%84%E6%94%AF%E6%8C%81%E5%8F%8A%E8%AE%B0%E5%BF%86%E5%8A%A0%E5%AF%86%E5%8D%87%E7%BA%A7%E7%89%88.html">上一章</a>   <a href="/wikis/">文档首页</a>   <a href="/wikis/%5B1.30%5D-%E4%BF%9D%E6%8C%81%E7%9A%84%E5%8A%9B%E9%87%8F%EF%BC%9A%E6%8E%A5%E5%8F%A3%E5%BC%80%E5%8F%91%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5.html">下一章</a></h4>
<hr />
<p><em>美国著名棒球运动员约格.贝拉说过：“通过仔细地观察，你可以了解很多事情。”</em>  </p>
<h2>1.29.1 绝对的开放，还是绝对的固化？</h2>
<p>框架应该都会考虑这样一个问题：到底是应该给应用项目提供统一固定的入口和初始化流程呢，还是应该给他们完全自由的空间？  </p>
<p>但我发现，很多PHP的框架都提供了一个绝对的固化流程。也就是你能作出改动的地方很少，虽然这样应用不需要过多地去考虑。  </p>
<p>然而我觉得，这样做，弊大于利。特别在现在项目需求背景各有各的不同时。所以，我为PhalApi框架选择了开放式的初始化做法。考虑到若开放的度太大，项目可能会迷茫，所以又结合了统一的初始化。  </p>
<p>下面分别说明这两点：开放式入口和封闭式的初始化。  </p>
<h2>1.29.2 开放式的入口</h2>
<p>作为一个接口系统，是需要为不同的终端、不同的开放人群，甚至不同的版本提供不同的服务的。  </p>
<p>如：  </p>
<ul>
<li>按不同的终端：iOS设备、Android设备、PC版、网页版</li>
<li>按不同的开放人群：手机客户端、内部管理后台、内部其他系统、公共开放平台</li>
<li>按不同的版本：版本从V1、V2到VN  </li>
<li>按不同的项目：同一个应用下可能会存在多个项目，当然更推荐每个项目单独一个系统</li>
</ul>
<p>基于此，为不同的维度提供不同的入口就很有现实实用场景了。  </p>
<p>更为重要的是，这些不同的入口都应该尽可能简单，并能统一共享公共的组件资源、数据库、日记系统这些。一个可能的入口示例如下：  </p>
<pre><code class="language-php">&lt;?php
/**
 * Demo 统一入口
 */

require_once dirname(__FILE__) . '/../init.php';

//装载你的接口
DI()-&gt;loader-&gt;addDirs('Demo');

/** ---------------- 响应接口请求 ---------------- **/

$api = new PhalApi();
$rs = $api-&gt;response();
$rs-&gt;output();</code></pre>
<p>简单解读一下上面的代码，首先要加载统一初始化文件，其实装载挂靠的接口项目（对应你的项目目录的名称），最后创建一个PhalApi接口实例进行响应、输出结果。  </p>
<p>下面来看下统一初始化文件需要做的事情。</p>
<h2>1.29.3 封闭式的初始化</h2>
<p>不言而喻，尽管我们有按不同维度划分入口的需要，但统一初始化的过程更是必不可少的。  </p>
<p>不同的入口提供了各维度定制的机会，统一的初始化则为应用提供了统一定制的机会。  </p>
<h3>(1)常规入口代码</h3>
<p>常规的入口，需要以下初始化操作：</p>
<pre><code class="language-php">&lt;?php
/**
 * 统一初始化
 */

/** ---------------- 根目录定义，自动加载 ---------------- **/

date_default_timezone_set('Asia/Shanghai');

defined('API_ROOT') || define('API_ROOT', dirname(__FILE__) . '/..');

require_once API_ROOT . '/PhalApi/PhalApi.php';
$loader = new PhalApi_Loader(API_ROOT);

/** ---------------- 注册&amp;初始化服务组件 ---------------- **/

//自动加载
DI()-&gt;loader = $loader;

//配置
DI()-&gt;config = new PhalApi_Config_File(API_ROOT . '/Config');

//日记纪录
DI()-&gt;logger = new PhalApi_Logger_File(API_ROOT . '/Runtime', 
    PhalApi_Logger::LOG_LEVEL_DEBUG | PhalApi_Logger::LOG_LEVEL_INFO | PhalApi_Logger::LOG_LEVEL_ERROR);

//数据操作 - 基于NotORM，$_GET['__sql__']可自行改名
DI()-&gt;notorm = function() {
    $debug = !empty($_GET['__sql__']) ? true : false;
    return new PhalApi_DB_NotORM(DI()-&gt;config-&gt;get('dbs'), $debug);
};

//调试模式，$_GET['__debug__']可自行改名
DI()-&gt;debug = !empty($_GET['__debug__']) ? true : DI()-&gt;config-&gt;get('sys.debug');

//翻译语言包设定
SL('zh_cn');</code></pre>
<h3>(2)常规代码解读</h3>
<p>上面是框架执行所需的基础服务注册和配置，一般直接可用，但也可以根据需要作些细微的调整。如日记的级别设定、调试的参数修改（改成一个只有自己知道的参数名字，别让外界知道！）等。 </p>
<p>出于让大家对初始化过程有一个更理性的认识，这里补充一下各代码的作用。  </p>
<p>最开始是利用了PHP原生态的时区设置和宏定义：  </p>
<pre><code class="language-php">date_default_timezone_set('Asia/Shanghai');

defined('API_ROOT') || define('API_ROOT', dirname(__FILE__) . '/..');</code></pre>
<p>接着，便开始引入PhalApi框架的类自动加载器：</p>
<pre><code class="language-php">require_once API_ROOT . '/PhalApi/PhalApi.php';
$loader = new PhalApi_Loader(API_ROOT);</code></pre>
<p>这样，我们就可以从原生态的PHP开发，切入到了PhalApi接口开发模式。但在捲起袖口准备大干一场前，我们还需要注册一些必备的服务：</p>
<pre><code class="language-php">//自动加载
DI()-&gt;loader = $loader;

//配置
DI()-&gt;config = new PhalApi_Config_File(API_ROOT . '/Config');

//日记纪录
DI()-&gt;logger = new PhalApi_Logger_File(API_ROOT . '/Runtime', 
    PhalApi_Logger::LOG_LEVEL_DEBUG | PhalApi_Logger::LOG_LEVEL_INFO | PhalApi_Logger::LOG_LEVEL_ERROR);

//数据操作 - 基于NotORM，$_GET['__sql__']可自行改名
DI()-&gt;notorm = function() {
    $debug = !empty($_GET['__sql__']) ? true : false;
    return new PhalApi_DB_NotORM(DI()-&gt;config-&gt;get('dbs'), $debug);
};</code></pre>
<p>上面的自动加载、配置、日记和数据库操作通常而言，对于一个项目都是必须的。<br />
但配置文件的路径可自行指定，日记的存储类型也可以自由组合（多个类型采用或运算），还可以选择你合适的数据库配置。
注意到，PhalApi_DB_NotORM初始化时，除了配置文件外，还有一个debug参数，此参数的作用是用于控制是否打印显示执行的SQL语句及对应消耗的时间。  </p>
<p>至此，我们已经为项目完成了绝大部分的基础服务注册，且上面的初始化顺序建议保留不变。因为，前后有依赖关系。  </p>
<p>但为了让我们的项目更有活力、更具生气、更国际化，我们还可以多加这么两行代码：</p>
<pre><code class="language-php">//调试模式，$_GET['__debug__']可自行改名
DI()-&gt;debug = !empty($_GET['__debug__']) ? true : DI()-&gt;config-&gt;get('sys.debug');

//翻译语言包设定
SL('zh_cn');</code></pre>
<p>这里，也有一个debug参数，之所以和数据库的分开，是因为如果混在一起会导致返回结果解析失败（如不再是JSON格式）。<br />
此debug的来源，默认来自环境的系统配置文件（如区分生产环境和测试环境）；也可以来自某个请求的手动设置，这样，开发同学便可以快速进行在线调试了。
而这个参数，则是框架代码、项目代码以及扩展类库所共用的调试开关，至于各个场景使用的效果，视各环节而定。  </p>
<p>SL()是一个快速函数，作用是设定翻译语言包。如果觉得中文下的UTF-8查看不直观，可以自行加个参数修改，如：</p>
<pre><code class="language-php">SL(isset($_GET['__lan__']) ? $_GET['__lan__'] : 'zh_cn');</code></pre>
<h3>(3)更多定制注册代码</h3>
<p>上面的操作，涵盖了大部分项目的需要。除此之外，还有一些额外的服务，可根据自身的情况，定制处理：</p>
<pre><code class="language-php">/** ---------------- 以下服务组件就根据需要定制注册 ---------------- **/

//缓存 - MC
/**
DI()-&gt;cache = function() {
    $mc = new PhalApi_Cache_Memcached(DI()-&gt;config-&gt;get('sys.mc'));
    return $mc;
};
 */

//签名验证服务
//DI()-&gt;filter = 'Common_SignFilter';

//支持JsonP的返回
if (!empty($_GET['callback'])) {
    DI()-&gt;response = new PhalApi_Response_JsonP($_GET['callback']);
}</code></pre>
<h3>(4)更多定制解读</h3>
<p>此部分的注册，非项目必须部分。可根据需要，自行定制。  </p>
<p>如上面出现的第一个，即缓存服务，使用的是Memcached：</p>
<pre><code class="language-php">DI()-&gt;cache = function() {
    $mc = new PhalApi_Cache_Memcached(DI()-&gt;config-&gt;get('sys.mc'));
    return $mc;
};</code></pre>
<p>接下来的，是重要的接口签名验证服务。之所以没有提供这个服务的实现，是出于更高安全性考虑而建议项目各自制定签名规则并实现。然后这样简单注册即可被框架自动调用：</p>
<pre><code class="language-php">//签名验证服务
//DI()-&gt;filter = 'Common_SignFilter';</code></pre>
<p>在有些需要支持JsonP返回的场景，可以使用PhalApi_Response_JsonP返回格式开放callback操作：</p>
<pre><code class="language-php">//支持JsonP的返回
if (!empty($_GET['callback'])) {
    DI()-&gt;response = new PhalApi_Response_JsonP($_GET['callback']);
}</code></pre>
<h2>1.29.4 用一张图来表示</h2>
<p><img src="http://webtools.qiniudn.com/%E5%A4%9A%E7%BA%A7%E7%BC%93%E5%AD%98%E9%9D%99%E6%80%81%E7%BB%93%E6%9E%84%E5%9B%BE-%E5%A4%9A%E5%85%A5%E5%8F%A3.jpg" alt="多级缓存静态结构图-多入口" /></p>
<hr />
<h4><a href="/wikis/%5B1.28%5D-COOKIE%EF%BC%9A%E5%AF%B9COOKIE%E5%8E%9F%E7%94%9F%E6%80%81%E7%9A%84%E6%94%AF%E6%8C%81%E5%8F%8A%E8%AE%B0%E5%BF%86%E5%8A%A0%E5%AF%86%E5%8D%87%E7%BA%A7%E7%89%88.html">上一章</a>   <a href="/wikis/">文档首页</a>   <a href="/wikis/%5B1.30%5D-%E4%BF%9D%E6%8C%81%E7%9A%84%E5%8A%9B%E9%87%8F%EF%BC%9A%E6%8E%A5%E5%8F%A3%E5%BC%80%E5%8F%91%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5.html">下一章</a></h4><div style="float: left">
<h4>
<a href="http://qa.phalapi.net/">还有疑问？欢迎到社区提问！</a>
</h4>
</div>
            </div>
        </div>
    </div>

 <!-- 广告位 -->
<div class="grid-wrapper desktop-only">
	<p align="center">
		<a href="http://7xiz2f.com1.z0.glb.clouddn.com/%E6%88%91%E7%9A%84%E5%90%8D%E5%AD%97%E5%8F%AB%EF%BC%9A%CF%80%E6%A1%86%E6%9E%B6%20-%20PhalApi%202016%E5%B9%B4%E5%BA%A6%E5%BC%80%E6%BA%90%E6%80%BB%E7%BB%93%20-%20%E5%AE%98%E6%96%B9%E5%87%BA%E5%93%81.pdf" target="blank"><img width="950" height="100" src="http://7xiz2f.com1.z0.glb.clouddn.com/ad_20170104.png"></a>
		<a href="http://www.itran.cc/" target="blank"><img width="950" height="100" src="http://7xslqv.com1.z0.glb.clouddn.com/images/9/69/b88bc92455dc1239f9a5bf8d72929.png"></a>
		<a href="http://web-tools.phalapi.net/" target="blank"><img width="950" height="100" src="http://7xslqv.com1.z0.glb.clouddn.com/images/7/d0/88f523566c482296aecc43d185ca2.png"></a>
	</p>
</div>

        <!-- footer -->
        <div class="footer">
            <div class="link container ">
                <div class=" col-xs-7 col-sm-7 col-md-7 col-lg-7 ">
                    <h3>PhalApi (π框架)</h3>
                    <p>一个轻量级PHP开源接口框架，专注于接口服务开发，支持HTTP/SOAP/RPC协议，拥有自动生成的在线文档、多种开发语言的客户端SDK包以及可重用的扩展类库，可用于快速搭建微服务、RESTful接口或Web
                        Services。</p>
                    <!-- <p>:</p> -->
                    <span>友情链接:</span>
                    <a href="https://www.phalapi.net/" target="_blank"> PhalApi </a>
                    <a href="http://www.oschina.net/" target="_blank"> 开源中国 </a>
                    <a href="https://www.itran.cc/" target="_blank">艾翻译</a>
                    <a href="http://www.phalconphp.com/en/" target="_blank">Phalcon</a>
                    <a href="https://phpunit.de/manual/3.7/zh_cn/automating-tests.html" target="_blank">PHPUnit</a>
                    <a href="http://www.thoughtworks.com/cn/" target="_blank">ThoughtWorks</a>
                    <a href="mailto:chanzonghuang@gmail.com">友链交换</a>

                </div>
                <div class=" col-xs-5 col-sm-5 col-md-5 col-lg-5 contact_us ">
                    <h3>联系我们</h3>
                    <a href="https://github.com/phalapi/phalapi"><img src="../images/github.png" alt="github" /></a>
                    <a href="http://weibo.com/p/100808d236e99beb645bfb56ed1c37dde9b8bd?k=phalapi%E5%BC%80%E6%BA%90%E6%A1%86%E6%9E%B6&from=501&_from_=huati_topic"><img src="../images/weibo.png"  alt="weibo" /></a>
                    <a href="http://7xslqv.com1.z0.glb.clouddn.com/images/1/b0/894fde762850cb11250253f7d5ede.png"><img src="../images/zfb.png"  alt="zfb" /></a>
                    <a href="https://jq.qq.com/?_wv=1027&k=4A6reum"><img src="../images/qq.png"  alt="qq" /></a>
					<a href="http://git.oschina.net/dogstar/PhalApi"><img src="../images/git-oschina.png"  alt="git-oschina" /></a>
                </div>
                <div class="cls"></div>
                <div class="text-center copy_right"> ©2015-2017 PhalApi All Rights Reserved. <a href="http://www.miitbeian.gov.cn" target="_blank">粤ICP备15028808号</a>

				<script type="text/javascript">var cnzz_protocol = (("https:" == document.location.protocol) ? " https://" : " http://");document.write(unescape("%3Cspan id='cnzz_stat_icon_1255326144'%3E%3C/span%3E%3Cscript src='" + cnzz_protocol + "s4.cnzz.com/z_stat.php%3Fid%3D1255326144%26show%3Dpic' type='text/javascript'%3E%3C/script%3E"));</script>
                </div>
            </div>
        </div>
    </div>


    <a href="https://github.com/phalapi"><img id="gitHub_fllow" style="position: fixed; top: 0; right: 0; border: 0;z-index:9999" src="https://camo.githubusercontent.com/652c5b9acfaddf3a9c326fa6bde407b87f7be0f4/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f6f72616e67655f6666373630302e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_right_orange_ff7600.png"></a>


    <script src="../js/jquery-1.11.1.min.js"></script>
    <script src="../js/bootstrap.min.js"></script>
</body>

</html>